/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package endpoint

import (
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/context"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/ichain"
	"github.com/pkg/errors"

	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/common/logging"
)

var logger = logging.NewLogger("ichainsdk/ichain")

type DiscoveryWrapper struct {
	ichain.DiscoveryService
	ctx      context.Client
	chInodes []ichain.ChainInode
}

func NewEndpointDiscoveryWrapper(ctx context.Client, chainID string, target ichain.DiscoveryService) (*DiscoveryWrapper, error) {
	inodes := ctx.EndpointConfig().ChainInodes(chainID)
	if len(inodes) == 0 {
		return nil, errors.Errorf("no chain inodes for chain [%s]", chainID)
	}

	s := &DiscoveryWrapper{
		DiscoveryService: target,
		chInodes:         inodes,
		ctx:              ctx,
	}
	return s, nil
}

func (s *DiscoveryWrapper) GetInodes() ([]ichain.Inode, error) {
	var eventEndpoints []ichain.Inode

	inodes, err := s.DiscoveryService.GetInodes()
	if err != nil {
		return nil, err
	}

	for _, inode := range inodes {

		var inodeConfig *ichain.InodeConfig
		var found bool

		chInode := s.getChainInode(inode.URL())
		if chInode != nil {
			inodeConfig = &chInode.InodeConfig
		} else {
			inodeConfig, found = s.ctx.EndpointConfig().InodeConfig(inode.URL())
			if !found {
				continue
			}
			chInode = s.getChainInode(inodeConfig.URL)
		}

		logger.Debugf("Chain inode config for [%s]: %#v", inode.URL(), chInode)

		if chInode != nil && !chInode.EventSource {
			logger.Debugf("Excluding inode [%s] since it is not configured as an event source", inode.URL())
			continue
		}

		eventEndpoint := FromInodeConfig(s.ctx.EndpointConfig(), inode, inodeConfig)
		eventEndpoints = append(eventEndpoints, eventEndpoint)
	}

	return eventEndpoints, nil
}

func (s *DiscoveryWrapper) getChainInode(url string) *ichain.ChainInode {
	for _, inode := range s.chInodes {
		if inode.URL == url {
			return &ichain.ChainInode{
				InodeChainConfig: inode.InodeChainConfig,
				NetworkInode:     inode.NetworkInode,
			}
		}
	}
	return nil
}
